package com.harveyspace.aes.social.clashroyale;

import com.harveyspace.aes.core.utils.JsonUtil;
import com.harveyspace.aes.social.Oauth;
import com.harveyspace.aes.social.SocialConfig;
import com.harveyspace.aes.social.exception.SocialException;
import com.harveyspace.aes.social.pojo.AccessTokenInfo;
import com.harveyspace.aes.social.pojo.SocialiteUserInfo;
import com.harveyspace.aes.social.utils.HttpClientSSL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 皇室战争
 *
 * @Author <a href="harveyer@163.com">harvey</a>
 * @date 2018/2/9
 */
public class OauthClashRoyale extends Oauth {

    private String TOKEN_URL;
    private String USER_INFO_URL;

    /**
     * @param socialConfig 配置信息
     */
    public OauthClashRoyale(SocialConfig socialConfig) {
        super(socialConfig);

        String baseUrl;
        switch (socialConfig.getEnvironment()) {
            case "production":
                baseUrl = "https://apiclashroyale.vpgame.com";
                break;
            default:
                baseUrl = "https://api-ext-2.clashroyale.com";
                break;
        }

        TOKEN_URL = baseUrl + "/v1/players/%s/verifytoken";
        USER_INFO_URL = baseUrl + "/v1/players/%s";
    }

    /**
     * 获取授权url
     *
     * @return String url
     */
    @Override
    public String getAuthorizeUrl(String state) {
        return null;
    }

    /**
     * 获取UserInfo
     *
     * @param openId      openid
     * @return String 返回类型
     * @throws SocialException 获取用户信息异常
     */
    private ClashRoyaleUserInfo getUserInfo(String openId) throws SocialException {

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + socialConfig.getClientAccessToken());

        String result;
        try {
            String userInfoUrl = String.format(USER_INFO_URL, URLEncoder.encode(openId, "utf-8"));
            result = HttpClientSSL.getString(userInfoUrl, headers);
        } catch (Exception e) {
            String errorMessage = String.format("通过 openid[%s] 获取用户信息异常", openId);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        if (null == result ||
                result.contains("reason")) {
            throw new SocialException(result);
        }

        return JsonUtil.toObject(result, ClashRoyaleUserInfo.class);
    }

    @Override
    public AccessTokenInfo getAccessToken(Map<String, String> request) throws SocialException {

        String tag = request.get("tag");

        if (tag == null || "".equals(tag)) {
            return null;
        }

        Map<String, Object> params = new HashMap<>();
        params.put("token", request.get("token"));

        String jsonParams = JsonUtil.toJsonString(params);

        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + socialConfig.getClientAccessToken());

        String result;
        try {
            String verifyTokenUrl = String.format(TOKEN_URL, URLEncoder.encode(tag, "utf-8"));
            result = HttpClientSSL.postForJson(verifyTokenUrl, jsonParams, headers);
        } catch (Exception e) {

            String errorMessage = String.format("通过 tag[%s] 获取 verify token 异常", tag);
            logger.error(errorMessage, e);
            throw new SocialException(errorMessage);
        }

        Map<String, String> responseMap = JsonUtil.toMap(result);
        String status = MapUtils.getString(responseMap, "status");

        if(StringUtils.isBlank(status) || !status.equals("ok")){
            throw new SocialException(String.format("通过 tag[%s] 获取 verify token 无效[%s]", tag, result));
        }

        AccessTokenInfo accessTokenInfo = new AccessTokenInfo();
        accessTokenInfo.setUnionId(tag);
        accessTokenInfo.setOpenId(tag);

        return accessTokenInfo;
    }

    @Override
    public SocialiteUserInfo getSocialUserInfo(AccessTokenInfo accessTokenInfo) throws SocialException {

        String openId = accessTokenInfo.getOpenId();

        if (StringUtils.isBlank(openId)) {
            throw new SocialException("openId is Blank!");
        }

        SocialiteUserInfo socialiteUserInfo = new SocialiteUserInfo();
        socialiteUserInfo.setUnionId(accessTokenInfo.getUnionId());
        socialiteUserInfo.setOpenId(accessTokenInfo.getOpenId());

        ClashRoyaleUserInfo info = getUserInfo(openId);

        if (null != info) {
            socialiteUserInfo.setName(info.getName());
            socialiteUserInfo.setNickName(info.getName());
        }

        return socialiteUserInfo;
    }
}